#!/bin/sh
#
# Copyright (C) 2000-2025 Kern Sibbald
# License: BSD 2-Clause; see file LICENSE-FOSS
#
# Bscan Test for the 'o' accurate backup option to backup only file's metadata
# if file contets did not change.
#

TestName="bscan-accurate-only-meta-test"
JobName=backup
. scripts/functions
$rscripts/cleanup

copy_test_confs
cp -f $rscripts/bacula-dir.conf.accurate $conf/bacula-dir.conf

change_jobname BackupClient1 $JobName

rm ${cwd}/build/testfile

cat <<END_OF_DATA >>${conf}/bacula-dir.conf
FileSet {
 Name = FS_META_TEST
 Include {
    Options {
      Signature = MD5
      Verify = mc
      #Accurate = mpin5o
      Accurate = c5o
    }
    File=<${cwd}/tmp/file-list
 }
}
END_OF_DATA

$bperl -e 'add_attribute("$conf/bacula-dir.conf", "FileSet", "FS_META_TEST" , "Job", "backup")'

echo "${cwd}/build" >${cwd}/tmp/file-list
# Add one more file
echo "testfile" >> ${cwd}/build/testfile

start_test

# Run normal backup
cat <<END_OF_DATA >${cwd}/tmp/bconcmds
@$out /dev/null
messages
label volume=TestVolume001 storage=File pool=Default
messages
@$out ${cwd}/tmp/log1.out
run job=$JobName yes
wait
messages
quit
END_OF_DATA

run_bacula

# Sleep for a few seconds, touch all files to change each file's metadata
sleep 3
files_count=`find ${cwd}/build -type f | wc -l`
find ${cwd}/build -type f -exec touch {} + > /dev/null
# Change some properties of testfile
chmod 777 ${cwd}/build/testfile
perm_after=`stat -c %a ${cwd}/build/testfile`

# Run backup for the second time, this time we expect that only metadata part for each file will be
# backed up, so we expect the backup size to be much smaller than the first one.
# Next purge and delete volume so that it can be bscanned later.
cat <<END_OF_DATA >${cwd}/tmp/bconcmds
@$out ${cwd}/tmp/log2.out
run job=$JobName yes
wait
messages
sql
@$out ${cwd}/tmp/log3.out
select count(*) from File;

@$out /dev/null
@$out ${cwd}/tmp/log4.out
purge volume=TestVolume001
delete volume=TestVolume001 yes
messages
quit
END_OF_DATA

run_bconsole

stop_bacula

# Check if number of second backup files equals to files touched
backup_files=`cat ${cwd}/tmp/log2.out | grep 'FD Files Written:' | tr -s ' ' | cut -d ':' -f 2 | sed s/,//`
if [ ${backup_files} -ne ${files_count} ]; then
   estat=1
   print_debug "Wrong number of files backed up: ${backup_files}, expected: ${files_count}"
fi

echo "volume=TestVolume001" >tmp/bscan.bsr

bscan_libdbi

# If the database has a password pass it to bscan
if test "x${db_password}" = "x"; then
  PASSWD=
else
  PASSWD="-P ${db_password}"
fi

# Run bscan
if test "$debug" -eq 1 ; then
  $bin/bscan -w working $BSCANLIBDBI -u ${db_user} -n ${db_name} $PASSWD -m -s -v -b tmp/bscan.bsr -c bin/bacula-sd.conf ${cwd}/tmp
else
  $bin/bscan -w working $BSCANLIBDBI -u ${db_user} -n ${db_name} $PASSWD -m -s -v -b tmp/bscan.bsr -c bin/bacula-sd.conf ${cwd}/tmp > tmp/log5.out 2>&1
fi

# Restore bscanned jobs
cat <<END_OF_DATA >${cwd}/tmp/bconcmds
sql
@$out ${cwd}/tmp/log6.out
select count(*) from File;

@$out /dev/null
@$out ${cwd}/tmp/log7.out
restore jobid=1,2 select all done yes
wait
messages
quit
END_OF_DATA

run_bacula

# Check if number if records inserted to the File table by bscan is correct
diff ${cwd}/tmp/log3.out ${cwd}/tmp/log6.out
if [ $? -ne 0 ]; then
   estat=1
   print_debug "Bscan inserted invalid number of File records! See ${cwd}/tmp/log3.out (expected) and ${cwd}/tmp/log6.out (bsanned)"
fi

# Check if testfile's restored permission are correctly changed
perm_restored=`stat -c %a ${cwd}/tmp/bacula-restores/${cwd}/build/testfile`
if [ ${perm_after} -ne ${perm_restored} ]; then
   estat=1
   print_debug "Wrong permissions restored: ${perm_restored}, expected: ${perm_after}"
fi

# Make sure that second backup was only some KB so that only metadata is transferred
bytes_written_kb=`cat tmp/log2.out | grep 'SD Bytes Written' | grep '(.* KB)' | wc -l`
if [ ${bytes_written_kb} -ne 1 ]; then
   estat=1
   print_debug "SD Bytes Written not expressed in KB as expected!"
fi

# Cleanup
rm ${cwd}/build/testfile

stop_bacula
end_test
